#ifndef PARSE_CFG_FILE_H
#define PARSE_CFG_FILE_H

#include <stdint.h>
#include <stdio.h>
#include "pointer_set.h"

/* For now this will just be a sorted array of pointers to strings.
 * Consider interning or whatever if performance becomes a problem. */
typedef struct _NAME_UNIVERSE _NAME_UNIVERSE, *NAME_UNIVERSE;
struct _NAME_UNIVERSE
{
    char **pool;
    size_t size, cap;
};

char *name_universe_find( char *name, NAME_UNIVERSE univ );

typedef struct _EDGE_LABEL _EDGE_LABEL, *EDGE_LABEL;
struct _EDGE_LABEL
{
    uint32_t id;
    uint64_t exec_ct;
    _PTR_SET live_in_to_succ;
};

typedef struct _EDGE_LINK _EDGE_LINK, *EDGE_LINK;
struct _EDGE_LINK
{
    uint32_t bbl, label;
};

typedef uint32_t AREG_FLAGS;
#define REGF_NONE       ((AREG_FLAGS)0x0)
#define REGF_READ_WRITE ((AREG_FLAGS)0x1)
#define REGF_IMPLICIT   ((AREG_FLAGS)0x2)

typedef struct _ANNOT_REG _ANNOT_REG, *ANNOT_REG;
struct _ANNOT_REG
{
    char *name, *full_name;
    AREG_FLAGS flags;
};

typedef uint32_t INSTR_FLAGS;
#define INSTRF_NONE                    ((INSTR_FLAGS)0x00)
#define INSTRF_HAS_FALL                ((INSTR_FLAGS)0x01)
#define INSTRF_MEM_READ                ((INSTR_FLAGS)0x02)
#define INSTRF_MEM_WRITE               ((INSTR_FLAGS)0x04)
#define INSTRF_TOO_MANY_READ_OPERANDS  ((INSTR_FLAGS)0x08)
#define INSTRF_TOO_MANY_WRITE_OPERANDS ((INSTR_FLAGS)0x10)

typedef struct _INSTR _INSTR, *INSTR;
struct _INSTR
{
    char *disas, *opc;
    uint8_t r_ct, w_ct;
    ANNOT_REG reads, writes;
    INSTR_FLAGS flags;
};

typedef uint32_t BBL_FLAGS;
#define BBLF_NONE           ((BBL_FLAGS) 0x0)
#define BBLF_IS_CALL        ((BBL_FLAGS) 0x1)
#define BBLF_IS_ENTRY       ((BBL_FLAGS) 0x2)
#define BBLF_IS_EXIT        ((BBL_FLAGS) 0x4)
#define BBLF_IS_STAT_RET    ((BBL_FLAGS) 0x8)
#define BBLF_IS_DYN_RET     ((BBL_FLAGS)0x10)
#define BBLF_DUMMY_CALL_RET ((BBL_FLAGS)0x20)

typedef struct _BBL_CTX _BBL_CTX, *BBL_CTX;
struct _BBL_CTX
{
    uint64_t exec_ct;
    /* preds and succs are arrays of indices into the edges arrays in the global context */
    uint32_t id, img_puid, pred_ct, pred_cap, succ_ct, succ_cap, ins_ct;
    EDGE_LINK preds, succs;
    INSTR inss;
    BBL_FLAGS flags;
    _PTR_SET local_live_ins, live_ins, writes, live_outs_any, live_outs_all;
};

typedef struct _IMG_CTX _IMG_CTX, *IMG_CTX;
struct _IMG_CTX
{
    char *name;
    uint32_t pin_id, puid;
};

extern uint32_t img_ct, bbl_ct, edge_ct, img_max_idx, bbl_max_idx, edge_max_idx;
extern IMG_CTX images;
extern BBL_CTX bbls;
extern EDGE_LABEL edges;
extern _NAME_UNIVERSE registers, opcodes;

void log_reg_set( PTR_SET s );
void log_bbl( BBL_CTX bbl );
void parse_cfg_file( FILE *f );

#endif
